package cz.semjob.document.util;

import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import cz.semjob.document.annotation.LabeledRelationWordsPair;
import cz.semjob.document.annotation.LabeledWords;
import cz.semjob.document.annotation.RelationWordsPair;
import cz.semjob.document.processing.DocumentWord;

public class DocumentUtil {

	private static final class WordIndexComparator implements
			Comparator<DocumentWord> {
		public int compare(DocumentWord o1, DocumentWord o2) {
			if (o1.getSentenceIndex() < o2.getSentenceIndex()) {
				return -1;
			}
			if (o1.getSentenceIndex() > o2.getSentenceIndex()) {
				return 1;
			}
			return 0;
		}
	}

	public static String printWords(List<DocumentWord> words) {
		Collections.sort(words, new WordIndexComparator());
		StringBuilder sb = new StringBuilder();
		for (DocumentWord documentWord : words) {
			sb.append(documentWord.getText() + " ");
		}
		return sb.deleteCharAt(sb.length() - 1).toString();
	}

	public static String printLemmaWords(List<DocumentWord> words) {
		Collections.sort(words, new WordIndexComparator());
		StringBuilder sb = new StringBuilder();
		for (DocumentWord documentWord : words) {
			sb.append(documentWord.getLinguisticWord().getLemma() + " ");
		}
		return sb.deleteCharAt(sb.length() - 1).toString();
	}

	public static String printLabeledRelation(
			LabeledRelationWordsPair labeledRelationWordsPair) {
		return labeledRelationWordsPair.getRelation().getName() + " "
				+ printRelation(labeledRelationWordsPair);
	}

	public static String printRelation(RelationWordsPair relationWordsPair) {
		StringBuilder sb = new StringBuilder();
		sb.append("(");
		sb.append(relationWordsPair.getEntity1().getName() + ": "
				+ printWords(relationWordsPair.getRelationWord1()) + ", ");
		sb.append(relationWordsPair.getEntity2().getName() + ": "
				+ printWords(relationWordsPair.getRelationWord2()) + ")");
		return sb.toString();
	}

	public static String printConcept(LabeledWords words) {
		return words.getLabel().getName() + ": "
				+ DocumentUtil.printWords(words.getWords());
	}

	public static List convertLabeledWordsList(
			List<LabeledWords> words) {
		List<List<DocumentWord>> documentWords = new ArrayList<List<DocumentWord>>();
		if (!words.isEmpty() && !(words.get(0) instanceof LabeledWords) ) {
			// we do not need to convert anything
			return words;
		}
		for (LabeledWords labeledWords : words) {
			documentWords.add(labeledWords.getWords());
		}
		return documentWords;
	}

	public static String createNormalizedRepresentation(String inputString) {
		
		String temp = Normalizer.normalize(inputString, Normalizer.Form.NFD);
		Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
		Pattern pattern2 = Pattern.compile(" ");
		temp = pattern.matcher(temp).replaceAll("");
		temp = pattern2.matcher(temp).replaceAll("_");
		temp = capitalize(temp);
		if (temp.indexOf('^') > 0) {
			temp = temp.substring(0, temp.indexOf('^'));
		}
		return temp;
	}
	
	private static String capitalize(String input) {
		char[] stringArray = input.toCharArray();
		stringArray[0] = Character.toUpperCase(stringArray[0]);
		return new String(stringArray);
	}
	
	public static boolean areWordsTextuallyEquals(List<DocumentWord> words1, List<DocumentWord> words2) {
		if (words1.size() != words2.size()) {
			return false;
		}
		for (int i = 0; i < words1.size(); i++) {
			
			if (!words1.get(i).getLinguisticWord().getLemma().equals(words2.get(i).getLinguisticWord().getLemma())) {
				return false;
			}
		}
		return true;
	}
	
	public static boolean areLabeledWordsEqual(LabeledWords words1, LabeledWords words2) {
		if (!words1.getLabel().equals(words2.getLabel())) {
			return false;
		}
		return areWordsTextuallyEquals(words1.getWords(), words2.getWords());
	}
	
	public static Collection<LabeledWords> removeDuplicates(Collection<LabeledWords> labeledWordsCollection) {
		    // ... the list is already populated
		   	List<LabeledWords>  words = new ArrayList<LabeledWords>(labeledWordsCollection);
		   	for (Iterator<LabeledWords> iterator = words.iterator(); iterator.hasNext();) {
		   		
				LabeledWords labeledWords = iterator.next();
				for (LabeledWords labeledWords2 : labeledWordsCollection) {
					if (!labeledWords2.equals(labeledWords) && areLabeledWordsEqual(labeledWords, labeledWords2)) {
						iterator.remove();
						break;
					}
				}
				
			}
		    return words;
	}

	public static int getStartIndex(List<DocumentWord> words) {
		Collections.sort(words, new WordIndexComparator());
		return words.get(0).getStartIndex();
	}
	
	public static int getEndIndex(List<DocumentWord> words) {
		Collections.sort(words, new WordIndexComparator());
		return words.get(words.size()-1).getEndIndex();
	}
}
